package com.depth.viewer.facade
{
	import com.depth.viewer.manager.IWidgetManager;
	import com.depth.viewer.manager.IWidgetRegistry;
	import com.depth.viewer.manager.ViewerSystemManager;
	import com.depth.viewer.utils.Util;
	import com.depth.viewer.widget.IBaseWidget;
	import com.depth.viewer.widget.definition.IBaseWidgetDefinition;
	import com.depth.viewer.widget.definition.IWidgetDefinition;
	
	import flash.events.Event;
	
	import mx.collections.ArrayCollection;
	
	import org.springextensions.actionscript.context.support.XMLApplicationContext;
	import org.springextensions.actionscript.puremvc.patterns.facade.IocFacade;
	import org.springextensions.actionscript.utils.ObjectUtils;
	
	public class WidgetFacade extends IocFacade implements IConfigurableWidgetFacade
	{
		private var _lookupObjects:ArrayCollection = new ArrayCollection();
		private var _widget:IBaseWidget;
		private var _widgetManager:IWidgetManager;
		public function WidgetFacade(key:String,p_configSource:*=null)
		{
			//TODO: implement function
			super(key,p_configSource);
			_widgetManager = ViewerSystemManager.getInstance().widgetManager;
		}
		override protected function onObjectFactoryListenerComplete(p_event:Event):void{
			super.onObjectFactoryListenerComplete(p_event);
		}
		public function set widget(widget:IBaseWidget):void{
			this._widget = widget;
		}
		public function get widget():IBaseWidget{
			return this._widget;
		}
		public function getObject(name:String):Object{
			var def:IBaseWidgetDefinition = _widget.definition as IBaseWidgetDefinition;
			try{
				var obj:Object = def.context.getObject(name);
				if(obj)
					return obj;
			}catch(err:Error){
				trace(err.message);
				trace(err.getStackTrace());
			}
			var importWidgets:Array = def.importWidgets;
			for each(var widgetName:String in importWidgets){
				var wFacade:IWidgetFacade = IocAppFacade.getInstance().getWidgetFacade(widgetName);
				try{
					obj = wFacade.getObject(name);
					if(obj){
						return obj;
					}
				}catch(err:Error){
					continue;
				}
			}
			return obj;
		}
		public function getObjectOfType(type:Class):Object{
			try{
				var obj:Object;
				var objectNames:Array = getObjectNamesForType(type);
				if(objectNames.length > 0){
					var objName:String = objectNames[0];
					obj = getObject(objName);
				}
				if(obj){
					return obj;
				}
			}catch(err:Error){
				trace(err.message);
				trace(err.getStackTrace());
			}
			return null;
		}
		public function getObjectsOfType(type:Class):Array{
			var objects:Array = [];
			var objectNames:Array = getObjectNamesForType(type);
			for each(var objName:String in objectNames){
				var obj:Object = getObject(objName);
				if(obj)
					objects.push(obj);
			}
			return objects;
		}
		public function getObjectNamesForType(type:Class):Array{
			var names:Array = [];
			var objNames:Array = container.getObjectNamesForType(type);
			names = names.concat(objNames);
			
			var def:IBaseWidgetDefinition = _widget.definition as IBaseWidgetDefinition;
			var importWidgets:Array = def.importWidgets;
			for each(var widgetName:String in importWidgets){
				try{
					var wFacade:IWidgetFacade = IocAppFacade.getInstance().getWidgetFacade(widgetName);
					var widgetNames:Array = wFacade.getObjectNamesForType(type);
					names = names.concat(widgetNames);
				}catch(err:Error){
					trace(err.getStackTrace());
					continue;
				}
			}
			return names;	
		}
		override public function sendNotification(notificationName:String, body:Object=null, type:String=null):void{
			if(type != widget.widgetId){
				super.sendNotification(notificationName,body,type);
			}
			if(!type){
				var def:IBaseWidgetDefinition = _widget.definition as IBaseWidgetDefinition;
				
				var importWidgets:Array = def.importWidgets;
				var exportsWidgets:Array = getExportWidgets();
				
				if(importWidgets){
					for each(var widgetName:String in importWidgets){
						var wDef:IWidgetDefinition = getWidgetDefinition(widgetName);
						var wFacade:IWidgetFacade;
						if(wDef){
							wFacade = wDef.facade as IWidgetFacade;
							if(wFacade){
								wFacade.sendNotification(notificationName,body,widget.widgetId);
							}else{
								trace("模块:  " + widgetName + "未加载 -----" + "此模块是依赖模块，必须加载才能正常提供功能服务");
							}
						}
					}
				}
				if(exportsWidgets){
					for each(var widgetName:String in exportsWidgets){
						var wDef:IWidgetDefinition = getWidgetDefinition(widgetName);
						var wFacade:IWidgetFacade = wDef.facade as IWidgetFacade;
						if(wFacade){
							wFacade.sendNotification(notificationName,body,widget.widgetId);
						}
					}
				}
			}
			
		}
		private function getWidgetDefinition(bundleId:String):IWidgetDefinition{
			return	_widgetManager.getRegistry().getRegistry().getRegistedWidgetDefinition(bundleId);
		}
		private function getExportWidgets():Array{
			var defs:Array = [];
			
			var widgetDefs:Array = _widgetManager.getRegistry().getRegistry().getRegistedWidgetDefinitions();
			var def:IBaseWidgetDefinition = _widget.definition as IBaseWidgetDefinition;
			for each(var wdef:IBaseWidgetDefinition in widgetDefs){
				var wImportWidgets:Array = wdef.importWidgets;
				if(wImportWidgets && wdef.id != _widget.widgetId){
					if(Util.indexOf(wImportWidgets,def.id) != -1){
						defs.push(wdef.id);
					}
				}
			}
			return defs;
		}
		public function lookup(type:Class):Array{
			var objs:Array = [];
			for each(var obj:Object in _lookupObjects){
				if(obj is type){
					objs.push(obj);
				}
			}
			var contextObjects:Array =  getObjectsOfType(type);
			Util.connect(objs,contextObjects);
			
			var def:IBaseWidgetDefinition = _widget.definition as IBaseWidgetDefinition;
			var importWidgets:Array = def.importWidgets;
			for each(var widgetName:String in importWidgets){
				var widget:IBaseWidget = ViewerSystemManager.getInstance().widgetManager.getRegistry().getRegistry().getRegistedWidget(widgetName);
				var widgetLookupOjbects:Array = IWidgetFacade(widget.definition.facade).lookup(type);
				Util.connect(objs,widgetLookupOjbects);
			}
			
			return objs;
		}
		
		public function addObject(object:Object):void{
			//判断上下文中是否有此实例
			var sameTypeObjects:Array = getObjectsOfType(ObjectUtils.getClass(object));
			for each(var obj:Object in sameTypeObjects){
				if(object == obj){
					return;
				}
			}
			//判断是否己存在
			var existentObject:Object;
			for each(var obj:Object in _lookupObjects){
				if(obj == object){
					existentObject = obj;
				}
			}
			if(existentObject){
				return;
			}
			_lookupObjects.addItem(object);
		}
		public 	function removeObjectByType(type:Class):void{
			for each(var obj:Object in _lookupObjects){
				if(obj is type){
					removeObject(obj);
				}
			}
		}
		public function removeObject(object:Object):void{
			var index:int = _lookupObjects.getItemIndex(object);
			if(index != -1){
				_lookupObjects.removeItemAt(index);
			}
		}
	}
}